#!/usr/bin/env python3
"""
游戏AI信号发送系统
基于录制的按键数据，智能分析并发送游戏控制信号
结合脑机接口架构，将按键序列转换为方向信号
"""

import json
import time
import socket
import threading
import argparse
import sys
import os
from datetime import datetime
from collections import deque, Counter
from pathlib import Path

class GameAISignalSender:
    def __init__(self, json_file_path, host='127.0.0.1', port=8888):
        """
        初始化游戏AI信号发送器
        
        Args:
            json_file_path: 录制数据的JSON文件路径
            host: 目标主机地址
            port: 目标端口
        """
        self.json_file_path = json_file_path
        self.host = host
        self.port = port
        self.socket = None
        self.events = []
        self.recording_info = {}
        self.running = False
        
        # 按键到方向的映射
        self.key_to_direction = {
            'W': '上',
            'A': '左', 
            'S': '下',
            'D': '右'
        }
        
        # 游戏模式检测
        self.game_patterns = {
            'platformer': ['SPACE', 'W', 'A', 'D'],  # 平台跳跃游戏
            'shooter': ['W', 'A', 'S', 'D', 'SHIFT', 'CTRL'],  # 射击游戏
            'racing': ['W', 'A', 'S', 'D'],  # 赛车游戏
            'rpg': ['W', 'A', 'S', 'D', 'SPACE', 'ENTER']  # RPG游戏
        }
        
        self.load_recording_data()
        self.analyze_game_pattern()
    
    def load_recording_data(self):
        """加载录制数据"""
        try:
            with open(self.json_file_path, 'r', encoding='utf-8') as f:
                data = json.load(f)
            
            self.recording_info = data.get('recording_info', {})
            self.events = data.get('events', [])
            
            print(f"✅ 成功加载游戏录制数据:")
            print(f"   📁 文件: {self.json_file_path}")
            print(f"   🎮 游戏: {self.recording_info.get('window_info', {}).get('title', 'Unknown')}")
            print(f"   ⏱️  时长: {self.recording_info.get('total_duration', 0):.2f}秒")
            print(f"   🎯 事件: {len(self.events)}")
            
        except Exception as e:
            print(f"❌ 加载录制数据失败: {e}")
            sys.exit(1)
    
    def analyze_game_pattern(self):
        """分析游戏模式"""
        keyboard_events = [e for e in self.events if e.get('type') == 'keyboard' and e.get('action') == 'down']
        if not keyboard_events:
            return
        
        # 统计按键使用频率
        key_counts = Counter([e.get('key_name', '') for e in keyboard_events])
        used_keys = set(key_counts.keys())
        
        # 检测游戏类型
        pattern_scores = {}
        for pattern_name, pattern_keys in self.game_patterns.items():
            score = len(used_keys.intersection(set(pattern_keys))) / len(pattern_keys)
            pattern_scores[pattern_name] = score
        
        best_pattern = max(pattern_scores, key=pattern_scores.get)
        confidence = pattern_scores[best_pattern]
        
        print(f"   🎯 游戏类型: {best_pattern} (置信度: {confidence:.2f})")
        print(f"   🔑 主要按键: {', '.join([k for k, v in key_counts.most_common(5)])}")
        
        # 分析移动模式
        movement_events = [e for e in keyboard_events if e.get('key_name') in self.key_to_direction]
        if movement_events:
            movement_sequence = [self.key_to_direction[e.get('key_name')] for e in movement_events]
            movement_counts = Counter(movement_sequence)
            print(f"   🧭 移动偏好: {dict(movement_counts)}")
    
    def connect_to_server(self):
        """连接到脑机信号处理服务器"""
        try:
            self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.socket.connect((self.host, self.port))
            print(f"✅ 已连接到脑机信号处理器 {self.host}:{self.port}")
            return True
        except Exception as e:
            print(f"❌ 连接失败: {e}")
            print("   💡 提示: 请先启动 signal_recv.py 脑机信号接收器")
            return False
    
    def extract_movement_signals(self, time_window=0.5):
        """
        从录制数据中提取移动信号序列
        
        Args:
            time_window: 时间窗口，将连续的按键合并为单个信号
        """
        keyboard_events = [e for e in self.events 
                          if e.get('type') == 'keyboard' 
                          and e.get('action') == 'down'
                          and e.get('key_name') in self.key_to_direction]
        
        if not keyboard_events:
            print("❌ 没有找到移动按键事件")
            return []
        
        signals = []
        last_time = 0
        last_direction = None
        
        for event in keyboard_events:
            direction = self.key_to_direction[event.get('key_name')]
            timestamp = event.get('timestamp', 0)
            
            # 时间窗口内的相同方向信号合并
            if direction == last_direction and (timestamp - last_time) < time_window:
                continue
            
            signals.append({
                'direction': direction,
                'timestamp': timestamp,
                'key': event.get('key_name')
            })
            
            last_direction = direction
            last_time = timestamp
        
        print(f"📡 提取移动信号序列: {len(signals)} 个信号")
        return signals
    
    def send_signal_sequence(self, signals, speed_multiplier=1.0, repeat_count=3):
        """
        发送信号序列到脑机处理器
        
        Args:
            signals: 信号序列
            speed_multiplier: 速度倍数
            repeat_count: 每个信号重复次数 (提高置信度)
        """
        if not self.socket:
            print("❌ 未连接到服务器")
            return
        
        if not signals:
            print("❌ 没有信号可发送")
            return
        
        print(f"\n🚀 开始发送游戏AI信号序列...")
        print(f"   📊 信号数量: {len(signals)}")
        print(f"   ⚡ 发送速度: {speed_multiplier}x")
        print(f"   🔄 重复次数: {repeat_count}")
        print("=" * 50)
        
        self.running = True
        previous_timestamp = 0
        
        try:
            for i, signal in enumerate(signals):
                if not self.running:
                    break
                
                direction = signal['direction']
                timestamp = signal['timestamp']
                
                # 等待到信号时间
                time_diff = (timestamp - previous_timestamp) / speed_multiplier
                if time_diff > 0:
                    time.sleep(min(time_diff, 2.0))  # 最大等待2秒
                
                # 重复发送信号提高置信度
                for j in range(repeat_count):
                    if not self.running:
                        break
                    
                    try:
                        data = f"{direction}\n"
                        self.socket.sendall(data.encode('utf-8'))
                        
                        current_time = datetime.now().strftime("%H:%M:%S.%f")[:-3]
                        progress = (i + 1) / len(signals) * 100
                        print(f"📡 [{current_time}] 发送: {direction} ({progress:.1f}%)")
                        
                        time.sleep(0.1)  # 信号间隔
                        
                    except Exception as e:
                        print(f"❌ 发送信号失败: {e}")
                        self.running = False
                        break
                
                previous_timestamp = timestamp
                
        except KeyboardInterrupt:
            print("\n⚠️  用户中断发送")
        finally:
            self.running = False
            print(f"\n✅ 信号序列发送完成")
    
    def send_real_time_signals(self, speed_multiplier=1.0):
        """实时发送信号，保持原始时间间隔"""
        signals = self.extract_movement_signals()
        if not signals:
            return
        
        print(f"\n🎮 实时模式发送游戏信号...")
        print(f"   ⏱️  原始时长: {self.recording_info.get('total_duration', 0):.1f}秒")
        print(f"   ⚡ 回放速度: {speed_multiplier}x")
        print(f"   ⏸️  按 Ctrl+C 停止")
        
        # 确认开始
        response = input("\n确认开始发送? (y/N): ").strip().lower()
        if response != 'y':
            print("❌ 发送已取消")
            return
        
        # 倒计时
        for i in range(3, 0, -1):
            print(f"⏰ {i}秒后开始...")
            time.sleep(1)
        
        self.send_signal_sequence(signals, speed_multiplier, repeat_count=3)
    
    def send_pattern_signals(self, pattern_name, duration=10.0):
        """
        发送模式化信号
        
        Args:
            pattern_name: 模式名称 ('circle', 'zigzag', 'random')
            duration: 持续时间(秒)
        """
        if not self.socket:
            print("❌ 未连接到服务器")
            return
        
        print(f"🎯 发送模式信号: {pattern_name} ({duration}秒)")
        
        patterns = {
            'circle': ['上', '右', '下', '左'] * 10,
            'zigzag': ['左', '右', '左', '右'] * 10,
            'random': ['上', '下', '左', '右'] * 10
        }
        
        if pattern_name not in patterns:
            print(f"❌ 不支持的模式: {pattern_name}")
            return
        
        pattern_signals = patterns[pattern_name]
        signal_interval = duration / len(pattern_signals)
        
        self.running = True
        try:
            for i, direction in enumerate(pattern_signals):
                if not self.running:
                    break
                
                # 重复发送3次提高置信度
                for _ in range(3):
                    data = f"{direction}\n"
                    self.socket.sendall(data.encode('utf-8'))
                    time.sleep(0.1)
                
                current_time = datetime.now().strftime("%H:%M:%S.%f")[:-3]
                progress = (i + 1) / len(pattern_signals) * 100
                print(f"🎯 [{current_time}] 模式信号: {direction} ({progress:.1f}%)")
                
                time.sleep(signal_interval)
                
        except KeyboardInterrupt:
            print("\n⚠️  用户中断模式发送")
        finally:
            self.running = False
            print(f"✅ 模式信号发送完成")
    
    def interactive_mode(self):
        """交互模式，手动发送信号"""
        if not self.socket:
            print("❌ 未连接到服务器")
            return
        
        print("\n🎮 交互模式已启动")
        print("输入方向(上/下/左/右)并按回车发送")
        print("输入 'auto' 开始自动回放")
        print("输入 'pattern <模式名>' 发送模式信号")
        print("输入 'quit' 退出")
        
        while True:
            try:
                user_input = input("\n🎯 > ").strip()
                
                if user_input.lower() == 'quit':
                    break
                elif user_input.lower() == 'auto':
                    self.send_real_time_signals()
                elif user_input.startswith('pattern '):
                    pattern_name = user_input.split(' ', 1)[1]
                    self.send_pattern_signals(pattern_name)
                elif user_input in ['上', '下', '左', '右']:
                    # 重复发送3次
                    for _ in range(3):
                        data = f"{user_input}\n"
                        self.socket.sendall(data.encode('utf-8'))
                        time.sleep(0.1)
                    
                    timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3]
                    print(f"📡 [{timestamp}] 手动发送: {user_input}")
                else:
                    print("❌ 无效输入！")
                    print("   可用命令: 上, 下, 左, 右, auto, pattern <模式>, quit")
                    
            except KeyboardInterrupt:
                break
            except Exception as e:
                print(f"❌ 交互模式错误: {e}")
                break
        
        print("👋 退出交互模式")
    
    def stop_sending(self):
        """停止发送"""
        self.running = False
        if self.socket:
            self.socket.close()
        print("🛑 信号发送已停止")

def find_json_files(directory):
    """查找目录下的JSON文件"""
    json_files = []
    for root, dirs, files in os.walk(directory):
        for file in files:
            if file.endswith('.json') and 'keystrokes' in file:
                json_files.append(os.path.join(root, file))
    return json_files

def main():
    parser = argparse.ArgumentParser(description="游戏AI信号发送系统")
    parser.add_argument('--file', '-f', type=str, help='JSON录制文件路径')
    parser.add_argument('--host', type=str, default='127.0.0.1', help='服务器地址')
    parser.add_argument('--port', '-p', type=int, default=8888, help='服务器端口')
    parser.add_argument('--speed', '-s', type=float, default=1.0, help='发送速度倍数')
    parser.add_argument('--interactive', '-i', action='store_true', help='交互模式')
    parser.add_argument('--pattern', type=str, help='发送模式信号 (circle/zigzag/random)')
    parser.add_argument('--duration', '-d', type=float, default=10.0, help='模式持续时间(秒)')
    parser.add_argument('--list', '-l', action='store_true', help='列出可用的录制文件')
    
    args = parser.parse_args()
    
    # 列出可用文件
    if args.list:
        print("🔍 搜索游戏录制文件...")
        json_files = find_json_files('pictures')
        if json_files:
            print(f"找到 {len(json_files)} 个录制文件:")
            for i, file in enumerate(json_files, 1):
                try:
                    with open(file, 'r', encoding='utf-8') as f:
                        data = json.load(f)
                    info = data.get('recording_info', {})
                    window_title = info.get('window_info', {}).get('title', 'Unknown')
                    duration = info.get('total_duration', 0)
                    
                    # 只显示游戏相关的录制
                    if 'Visual Studio Code' not in window_title:
                        print(f"  {i}. {file}")
                        print(f"     🎮 游戏: {window_title}")
                        print(f"     ⏱️  时长: {duration:.1f}秒")
                except:
                    pass
        else:
            print("❌ 未找到录制文件")
        return
    
    # 检查文件参数
    if not args.file:
        print("❌ 请指定JSON录制文件路径")
        print("使用 --list 查看可用文件")
        return
    
    if not os.path.exists(args.file):
        print(f"❌ 文件不存在: {args.file}")
        return
    
    # 创建信号发送器
    sender = GameAISignalSender(args.file, args.host, args.port)
    
    # 连接到服务器
    if not sender.connect_to_server():
        return
    
    try:
        # 交互模式
        if args.interactive:
            sender.interactive_mode()
        
        # 模式信号
        elif args.pattern:
            sender.send_pattern_signals(args.pattern, args.duration)
        
        # 自动回放
        else:
            sender.send_real_time_signals(args.speed)
            
    except KeyboardInterrupt:
        print("\n⚠️  用户中断")
    finally:
        sender.stop_sending()

if __name__ == "__main__":
    main()
